package com.ruoyi.finance.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.*;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.finance.config.ThreadPoolExecutorConfig;
import com.ruoyi.finance.domain.vo.CredentialRollupVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.finance.mapper.TVoucherDetailMapper;
import com.ruoyi.finance.domain.TVoucherDetail;
import com.ruoyi.finance.service.ITVoucherDetailService;

import javax.servlet.http.HttpServletResponse;

/**
 * 凭证明细Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-02-26
 */
@Service
public class TVoucherDetailServiceImpl
        extends ServiceImpl<TVoucherDetailMapper, TVoucherDetail>
        implements ITVoucherDetailService
{
    @Autowired
    private TVoucherDetailMapper tVoucherDetailMapper;

    @Autowired
    RedisService redisService;

    @Autowired
    ThreadPoolExecutor threadPoolExecutor;

    /**
     * 查询凭证明细
     * 
     * @param voucherDetailId 凭证明细主键
     * @return 凭证明细
     */
    @Override
    public TVoucherDetail selectTVoucherDetailByVoucherDetailId(Long voucherDetailId)
    {
        return tVoucherDetailMapper.selectTVoucherDetailByVoucherDetailId(voucherDetailId);
    }

    /**
     * 查询凭证明细列表
     * 
     * @param tVoucherDetail 凭证明细
     * @return 凭证明细
     */
    @Override
    public List<TVoucherDetail> selectTVoucherDetailList(TVoucherDetail tVoucherDetail)
    {
        return tVoucherDetailMapper.selectTVoucherDetailList(tVoucherDetail);
    }

    /**
     * 新增凭证明细
     * 
     * @param tVoucherDetail 凭证明细
     * @return 结果
     */
    @Override
    public int insertTVoucherDetail(TVoucherDetail tVoucherDetail)
    {
        return tVoucherDetailMapper.insertTVoucherDetail(tVoucherDetail);
    }

    /**
     * 修改凭证明细
     * 
     * @param tVoucherDetail 凭证明细
     * @return 结果
     */
    @Override
    public int updateTVoucherDetail(TVoucherDetail tVoucherDetail)
    {
        return tVoucherDetailMapper.updateTVoucherDetail(tVoucherDetail);
    }

    /**
     * 批量删除凭证明细
     * 
     * @param voucherDetailIds 需要删除的凭证明细主键
     * @return 结果
     */
    @Override
    public int deleteTVoucherDetailByVoucherDetailIds(Long[] voucherDetailIds)
    {
        return tVoucherDetailMapper.deleteTVoucherDetailByVoucherDetailIds(voucherDetailIds);
    }

    /**
     * 删除凭证明细信息
     * 
     * @param voucherDetailId 凭证明细主键
     * @return 结果
     */
    @Override
    public int deleteTVoucherDetailByVoucherDetailId(Long voucherDetailId)
    {
        return tVoucherDetailMapper.deleteTVoucherDetailByVoucherDetailId(voucherDetailId);
    }

    @Override
    public Map<String, Object> selectCredentialRollupList(CredentialRollupVo credentialRollupVo) {


        HashMap<String, Object> CredentialRollup = new HashMap<>();
        //总借方金额
        BigDecimal allDebitAmount = new BigDecimal(0);
        //总贷方金额
        BigDecimal allCreditAmount = new BigDecimal(0);
        //总数
        Integer all = 0;
        //合计
        BigDecimal Amount = new BigDecimal(0);
        //凭证总张数
        Integer voucherCount = 0;
        //附单据总数
        Integer voucherWordCount = 0;


        if (credentialRollupVo.getStartTime() != null && credentialRollupVo.getEndTime() != null) {
            if (credentialRollupVo.getStartTime().after(credentialRollupVo.getEndTime())) {
                System.out.println("开始时间不能大于结束时间");
                throw new RuntimeException("开始时间不能大于结束时间");
            }
        }
        if (credentialRollupVo.getStartAccountId() != null && credentialRollupVo.getEndAccountId() != null) {
            if (credentialRollupVo.getStartAccountId() > credentialRollupVo.getEndAccountId()) {
                System.out.println("开始科目不能大于结束科目");
                throw new RuntimeException("开始科目不能大于结束科目");
            }
        }

        List<CredentialRollupVo> list = tVoucherDetailMapper.selectCredentialRollupList(credentialRollupVo);

        voucherCount = tVoucherDetailMapper.selectvoucherCount();

        voucherWordCount = tVoucherDetailMapper.selectvoucherWordCount();

        //循环累加借方和贷方金额
        for (CredentialRollupVo rollupVo : list) {
            //总借方金额
            allDebitAmount = allDebitAmount.add(rollupVo.getDebitAmount());
            //总贷方金额
            allCreditAmount = allCreditAmount.add(rollupVo.getCreditAmount());
        }
        //合计
//        Amount = allDebitAmount.subtract(allCreditAmount);


        //总借方金额
//        CredentialRollup.put("allDebitAmount",list.stream().map(CredentialRollupVo::getDebitAmount).reduce(BigDecimal::add).get());
        //总贷方金额
//        CredentialRollup.put("allCreditAmount",list.stream().map(CredentialRollupVo::getCreditAmount).reduce(BigDecimal::add).get());
        //总数
//        CredentialRollup.put("all",tVoucherDetailMapper.selectCredentialRollupList(credentialRollupVo).size());        //数据
        CredentialRollup.put("list", list);
        //合计
//        CredentialRollup.put("Amount",Amount);
        //总凭证张数
        CredentialRollup.put("voucherCount", voucherCount);
        //附单据总数
        CredentialRollup.put("voucherWordCount", voucherWordCount);


        return CredentialRollup;
    }


    @Override
    public void export(HttpServletResponse response, CredentialRollupVo credentialRollupVo) {

        List<CredentialRollupVo> list = tVoucherDetailMapper.selectCredentialRollupList(credentialRollupVo);
        ExcelUtil<CredentialRollupVo> util = new ExcelUtil<>(CredentialRollupVo.class);
        // 获取凭证汇总数据
//        List<CredentialRollupVo> list = (List<CredentialRollupVo>) map.get("list");
        // 创建线程池配置


        try {
            int batchSize = 1000; // 每个线程处理的数据量
            List<Future<List<CredentialRollupVo>>> futures = new ArrayList<>();

            // 数据分片
            for (int i = 0; i < list.size(); i += batchSize) {
                int end = Math.min(i + batchSize, list.size());
                List<CredentialRollupVo> subList = list.subList(i, end);

                // 提交任务到线程池
                Future<List<CredentialRollupVo>> future = threadPoolExecutor.submit(() -> {
                    List<CredentialRollupVo> processedData = new ArrayList<>();

                    for (CredentialRollupVo dto : subList) {
                        try {
                            // 1. 数据格式校验和转换
                            if (dto != null) {
                                // 2. 金额计算和汇总
                                // 确保金额字段不为空
                                if (dto.getDebitAmount() == null) {
                                    dto.setDebitAmount(BigDecimal.valueOf(0.0));
                                }
                                if (dto.getCreditAmount() == null) {
                                    dto.setCreditAmount(BigDecimal.valueOf(0.0));
                                }


                                // 5. 性能优化处理
                                // 使用批量处理减少内存占用
                                processedData.add(dto);
                            }
                        } catch (Exception e) {
                            // 记录异常但继续处理其他数据
                            e.printStackTrace();
                            System.out.println("处理异常：" + e.getMessage());
                        }
                    }

                    return processedData;
                });
                futures.add(future);
            }

            // 等待所有任务完成并合并结果
            List<CredentialRollupVo> processedList = new ArrayList<>();
            for (Future<List<CredentialRollupVo>> future : futures) {
                processedList.addAll(future.get());
            }

            // 导出到Excel
            util.exportExcel(response, processedList, "凭证详情数据");

        } catch (Exception e) {

            throw new RuntimeException("导出失败：" + e.getMessage());
        }
    }
}


//    @Override
//    public List<CredentialRollupVo> selectCredentialRollupList(CredentialRollupVo credentialRollupVo) {
//
////        Date startTime = credentialRollupVo.getStartTime();
////        Date endTime = credentialRollupVo.getEndTime();
//
//
//
//
//        if(credentialRollupVo.getStartTime()!=null && credentialRollupVo.getEndTime()!=null){
//            if (credentialRollupVo.getStartTime().after(credentialRollupVo.getEndTime())){
//                System.out.println("开始时间不能大于结束时间");
//                throw new RuntimeException("开始时间不能大于结束时间");
//            }
//        }
//        if (credentialRollupVo.getStartAccountId()!=null && credentialRollupVo.getEndAccountId()!=null){
//            if (credentialRollupVo.getStartAccountId()>credentialRollupVo.getEndAccountId()){
//                System.out.println("开始科目不能大于结束科目");
//                throw new RuntimeException("开始科目不能大于结束科目");
//            }
//        }
//
//        return tVoucherDetailMapper.selectCredentialRollupList(credentialRollupVo);
//    }



